package de.uni.muenster.mmm.AndroidCieLab.calculation;


public class RGBtoCieLab {

	// treshold for small values in XYZ to CieLab transformation
	private static final double TRESH = 0.008856;
	
	// parameters for rgb to xyz transformation
	private static final float [][] RGB2XYZ_TRANS = 
			{{0.412453f, 0.357580f, 0.180423f},
			{0.212671f, 0.715160f, 0.072169f},
			{0.019334f, 0.119193f, 0.950227f}};
	
	// parameters for D65 white point normalization
	private static final float X_N = 0.950456f;
	private static final float Z_N = 1.088754f;
	
	public static float[] RGB2Cie (float [] rgb){
		// durch 255 teilen
		rgb[0] = rgb[0]/255;
		rgb[1] = rgb[1]/255;
		rgb[2] = rgb[2]/255;
		
		// von RGB zu XYZ
		float [] xyz = RGB2XYZ(rgb);
		
		// von XYZ zu CieLab
		
		return XYZ2Cie(xyz);
	}
	
	
	private static float[] RGB2XYZ (float [] rgb){
		float [] xyz = new float [3];
		xyz[0] = rgb[0]* RGB2XYZ_TRANS[0][0] + rgb[1]* RGB2XYZ_TRANS[0][1] + rgb[2]* RGB2XYZ_TRANS[0][2];
		xyz[1] = rgb[0]* RGB2XYZ_TRANS[1][0] + rgb[1]* RGB2XYZ_TRANS[1][1] + rgb[2]* RGB2XYZ_TRANS[1][2];
		xyz[2] = rgb[0]* RGB2XYZ_TRANS[2][0] + rgb[1]* RGB2XYZ_TRANS[2][1] + rgb[2]* RGB2XYZ_TRANS[2][2];
		

	      //D65 white point normalization
	      xyz[0] = xyz[0]/X_N;
	      xyz[2] = xyz[2]/Z_N;
	    
		
		return xyz;
	}
	
	private static float[] XYZ2Cie (float [] xyz){

		float [] fXYZ = new float [3];
		float y3 = (float)Math.cbrt((double)xyz[1]);
		
		// X
		boolean xt = xyz[0]>TRESH;
		if (xt) fXYZ[0] = (float)Math.cbrt((double)xyz[0]);
		else fXYZ[0] = 7.787f * xyz[0] + 16/116;

		// Y
		boolean yt = xyz[1]>TRESH;
		if (yt) fXYZ[1] = y3;		
		else fXYZ[1] = 7.787f * xyz[1] + 16/116;		
		
		// Z
		boolean zt = xyz[2]>TRESH;
		if (zt) fXYZ[2] = (float)Math.cbrt((double)xyz[2]);
		else fXYZ[2] = 7.787f * xyz[2] + 16/116;
		
		
		float [] lab = new float [2]; // 3
//		// L
//		if (yt) lab[0] = 116* y3 -16;
//		else lab[0] =903.3f* xyz[1];
		
		// a
		lab[0] = 500 * (fXYZ[0] - fXYZ[1]); //1
		
		// b
		lab[1] = 200 * (fXYZ[1] - fXYZ[2]); //2
		
		return lab;
	}
}
